import { Util } from '../../utils/util.js';
import { Definition } from '../common/definition.js';
import { CsDouble } from '../common/csDouble.js';
import { PermissionInfo } from '../menus/permissionInfo.js';
import { MerchantPackageAuthAccount } from '../merchantOrg/merchantPackageAuthAccount.js';

export class MerchantPackageFilter {
    constructor() {
        this.orgName = null;
        this.orgId = null;
    }

    clear() {
        this.orgName = null;
        this.orgId = null;
    }

    static clone(filter) {
        const f = new MerchantPackageFilter();
        f.orgName = filter.orgName;
        f.orgId = filter.orgId;
        return f;
    }

    toJson() {
        const ret = {};
        if (this.orgName) ret["lke_name"] = this.orgName;
        if (this.orgId) ret["orgId"] = this.orgId;
        return ret;
    }
}

export class MerchantPackage {

    static empty() {
        return new MerchantPackage({
            id: "",
            name: "",
            orgId: "",
            platformPkgId: "",
            startDate: new Date(),
            endDate: new Date(),
            authAccountData: [],
            isTrialMode: false,
            price: 0,
            discountPrice: null,
            spanMonth: 0,
            pkgLimitation: "",
            pkgPermission: "",
            minAccountNum: 1,
            orgName: ""
        });
    }
    constructor({
        id = "",
        name = "",
        orgId = "",
        platformPkgId = "",
        startDate = new Date(),
        endDate = new Date(),
        authAccountData = [],
        isTrialMode = false,
        price = 0,
        discountPrice = null,
        spanMonth = 0,
        pkgLimitation = "",
        pkgPermission = "",
        minAccountNum = 1,
        orgName = ""
    } = {}) {
        this.id = id;
        this.name = name;
        this.orgId = orgId;
        this.platformPkgId = platformPkgId;
        this.startDate = new Date(startDate);
        this.endDate = new Date(endDate);
        this.authAccountData = authAccountData;
        this.isTrialMode = isTrialMode;
        this.price = price;
        this.discountPrice = discountPrice;
        this.spanMonth = spanMonth;
        this.pkgLimitation = pkgLimitation;
        this.pkgPermission = pkgPermission;
        this.minAccountNum = minAccountNum;
        this.orgName = orgName;

        this.permissionInfo = new PermissionInfo();
        this.parsePermission();
    }

    static fromJson(json) {
        return new MerchantPackage({
            id: Util.jsonToString(json["id"]),
            name: Util.jsonToString(json["name"]),
            orgId: Util.jsonToString(json["orgId"]),
            orgName: Util.jsonToString(json["orgName"]),
            platformPkgId: Util.jsonToString(json["packageId"]),
            startDate: json["startServerTime"] ? new Date(json["startServerTime"]) : new Date(),
            endDate: json["endServerTime"] ? new Date(json["endServerTime"]) : new Date(),
            authAccountData: MerchantPackageAuthAccount.getAccountList(json["authData"]),
            isTrialMode: Util.jsonToBool(json["tryuse"], false),
            price: Util.jsonToDouble(json["price"], 0),
            discountPrice: Util.jsonToDouble(json["discountPrice"], 0),
            spanMonth: Util.jsonToInt(json["spanMonth"]),
            pkgLimitation: Util.jsonToString(json["dataLimitation"]),
            pkgPermission: Util.jsonToString(json["permission"]),
            minAccountNum: Math.max(Util.jsonToInt(json["minAccountCount"], 1), 1)
        });
    }

    toJson() {
        return {
            id: this.id,
            name: this.name,
            orgId: this.orgId,
            packageId: this.platformPkgId,
            startServerTime: this.startDate.toISOString(),
            endServerTime: this.endDate.toISOString(),
            authData: MerchantPackageAuthAccount.accountListJsonString(this.authAccountData),
            tryuse: this.isTrialMode ? 1 : 0,
            price: this.price,
            discountPrice: this.discountPrice,
            spanMonth: this.spanMonth,
            dataLimitation: this.pkgLimitation,
            permission: this.getPermissionJson(),
            minAccountCount: this.minAccountNum
        };
    }

    parsePermission() {
        if (this.pkgPermission) {
            try {
                const jsonData = JSON.parse(this.pkgPermission);
                this.permissionInfo = PermissionInfo.fromJson(jsonData);
            } catch (e) {
                console.log("MerchantPackage failed to parse permission data:" + e);
            }
        }
    }

    getPermissionJson() {
        if (this.permissionInfo.menuTree && this.permissionInfo.menuTree.length > 0) {
            return JSON.stringify(this.permissionInfo.toJson());
        }
        return "";
    }

    getPurchasePrice() {
        const realPrice = this.discountPrice == null ? this.price : (this.price - this.discountPrice);
        return new CsDouble(realPrice, Definition.gConstmerchantChargeNumPrecision).value;
    }

    removeAuthAccount(account) {
        const index = this.authAccountData.indexOf(account);
        if (index !== -1) {
            this.authAccountData.splice(index, 1);
        }
    }

    addAuthAccount(account) {
        for (const item of this.authAccountData) {
            if (item.startTime.getTime() === account.startTime.getTime() &&
                item.endTime.getTime() === account.endTime.getTime()) {
                return false;
            }
        }
        this.authAccountData.push(account);
        return true;
    }

    updateAuthAccount(batch, orgBatch) {
        const index = this.authAccountData.indexOf(orgBatch);
        if (index >= 0) {
            for (const item of this.authAccountData) {
                if (item !== orgBatch &&
                    item.startTime.getTime() === batch.startTime.getTime() &&
                    item.endTime.getTime() === batch.endTime.getTime()) {
                    return false;
                }
            }
            this.authAccountData[index] = batch;
            return true;
        }
        return false;
    }

    getActiveAccountNum() {
        const now = new Date();
        return this.authAccountData.reduce((acc, item) => {
            return (now > item.startTime && now < item.endTime) ? acc + item.count : acc;
        }, 0);
    }

    getTotalAccountNum() {
        return this.authAccountData.reduce((acc, item) => acc + item.count, 0);
    }

    getAccountNumForPurchase() {
        let activeAccount = this.getActiveAccountNum();
        if (activeAccount > 0) return activeAccount;

        let latestTime = null;
        for (const item of this.authAccountData) {
            if (!latestTime || item.endTime > latestTime) {
                latestTime = item.endTime;
                activeAccount = item.count;
            }
        }
        return activeAccount;
    }

    isAccountPeriodMatchedPkgPeriod(account) {
        return account.startTime.getTime() === this.startDate.getTime() &&
            account.endTime.getTime() === this.endDate.getTime();
    }
}
